package com.bto.solar.work.exception;

import com.bto.solar.work.common.BizException;
import com.bto.solar.work.common.BizLoginException;
import com.bto.solar.work.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Objects;

/**
 * 全局异常处理
 *
 * @Author Created by 2022 on 2023/4/22.
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(BizException.class)
    public R handlerBusinessException(BizException bizException) {
        bizException.printStackTrace();
        log.error("exception happened at message {} throw {} ", bizException.getMessage() , bizException.getStackTrace());
        return R.fail(bizException.getMessage());
    }

    @ExceptionHandler(BizLoginException.class)
    @ResponseStatus(value = HttpStatus.UNAUTHORIZED)
    public R handlerLoginException(BizLoginException bizLoginException) {
        bizLoginException.printStackTrace();
        log.error("exception happened at message {} throw {} ", bizLoginException.getMessage() , bizLoginException.getStackTrace());
        return R.fail(bizLoginException.getCode().intValue(), bizLoginException.getMessage());
    }

    /**
     * 参数异常
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseBody
    public R parameterCheckHandle(MethodArgumentNotValidException exception) {
        exception.printStackTrace();
        BindingResult result = exception.getBindingResult();
        StringBuilder errorMsg = new StringBuilder();
        if (result.hasErrors()) {
            List<FieldError> fieldErrors = result.getFieldErrors();
            fieldErrors.forEach(error -> {
                log.error("field: " + error.getField() + ", msg: " + error.getDefaultMessage());
                errorMsg.append(error.getDefaultMessage()).append("!");
            });
        }
        exception.printStackTrace();
        return R.fail(errorMsg.toString());
    }

    /**
     * 约束违反异常
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    @ResponseBody
    public R parameterCheckHandle(ConstraintViolationException exception) {
        return R.fail(exception.getMessage());
    }

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public R parameterCheckHandle(Exception exception) {
        exception.printStackTrace();
        return R.fail(exception.getMessage());
    }

    //处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public R BindExceptionHandler(BindException e) {
        return R.fail(Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
    }
}